import json
import os

class Configuration:
    config_path='clock.json'
    default_slience=[0,1,2,3,4,5,6]
    default_ticks=[30]
    default_settings={
        'slience':default_slience.copy(),
        'ticks':default_ticks.copy(),
        'notifiers':{
        },
    }

    def __init__(self,new=False) -> None:
        if new:
            self.settings=self.default_settings
        else:
            self.settings=self.read()

    def read(self):
        if os.path.exists(self.config_path)==False:
            return self.default_settings
        with open(self.config_path ,encoding='utf8') as f:
            try:
                config= json.load(f)
                if isinstance(config,dict)==False:
                    return self.default_settings
                else:
                    return config
            except:
                return self.default_settings
    
    def save(self):
        with open(self.config_path,'w',encoding='utf8') as f:
            json.dump(self.settings,f)
    
    def update(self,settings):
        state=self.validate_settings(settings)
        if isinstance(state,Exception):
            return state
        state=self.parse_settings(settings)
        if isinstance(state,Exception):
            return state
        self.settings.update(settings)
        self.save()
        return True
    
    @property
    def ticks(self):
        return self.settings['ticks']
    
    @property
    def slience(self):
        return self.settings['slience']
    
    @property
    def notifiers(self)->dict:
        return self.settings['notifiers']


    @classmethod
    def validate_settings(cls,settings:dict):
        if isinstance(settings,dict)==False:
            return Exception('Settings are not dict:',str(settings))
        default_keys=cls.default_settings.keys()
        keys=settings.keys()
        if len(keys)!=len(default_keys):
            return Exception('Invalid key length!')
        for key in default_keys:
            if key not in keys:
                return Exception(f'Missing key:{key}')
            val_type=type(cls.default_settings[key])
            if type(settings[key])!=val_type:
                return Exception(f'Invalid value type for key:{key}')
        
        return True

    @classmethod
    def parse_settings(cls,settings:dict):
        ticks=[]
        for tick in settings['ticks']:
            try:
                ticks.append(int(tick))
            except:
                return Exception('Can not parse tick to int:',str(tick))
        settings['ticks']=sorted(ticks)

        slience=[]
        for s in settings['slience']:
            try:
                slience.append(int(s))
            except:
                return Exception('Can not parse slience to int:',str(s))
        settings['slience']=slience
        return settings




